#include "usersmg.h"



//#define SMG_SET_S0_LIGHTNESS(x)  htim3.Instance->CCR3=x*25;
//#define SMG_SET_S1_LIGHTNESS(x)  htim3.Instance->CCR4=x*25;
//#define SMG_SET_S2_LIGHTNESS(x)  htim3.Instance->CCR1=x*25;
//#define SMG_SET_S3_LIGHTNESS(x)  htim3.Instance->CCR2=x*25;

#define SMG_S0_TIME_CH TIM_CHANNEL_3
#define SMG_S1_TIME_CH TIM_CHANNEL_4
#define SMG_S2_TIME_CH TIM_CHANNEL_1
#define SMG_S3_TIME_CH TIM_CHANNEL_2

#define SMG_BLINK_NONE  		 0X00
#define SMG_BLINK				 0X01

#define SMG_SET_DATA(i)   GPIOA->ODR&=0XFF00;GPIOA->ODR|=i;



const static uint8_t  numtab[17]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x40};   //共阴数码管编码

void user_smgRollScan(void);
void user_smgNormalScan(void);
uint8_t setDisWei(uint8_t s);

void smgClass::init()
{
	HAL_TIM_PWM_Start(&htim3,SMG_S0_TIME_CH);
	HAL_TIM_PWM_Start(&htim3,SMG_S1_TIME_CH);    
	HAL_TIM_PWM_Start(&htim3,SMG_S2_TIME_CH);    
	HAL_TIM_PWM_Start(&htim3,SMG_S3_TIME_CH);    
	    
	//设置默认亮度
	lighteness=2;
	//数码管都先关闭
	setDisWei(SMG_S_NONE);
	//关闭数码管闪烁功能
	clearBlink();
	//设置默认显示模式
	disMode=SMG_DIS_MODE_NORMAL;	

}

void smgClass::setDisMode(uint8_t mode)
{
	if(mode==SMG_DIS_MODE_ROLL)
	{
		disMode=SMG_DIS_MODE_ROLL;
	}
	else
	{
		disMode=SMG_DIS_MODE_NORMAL;
	}
}



//设置一位数码管亮度,亮度等级0-5
//s:0-3
//l: 0-10   0关闭显示，3显示最亮
uint8_t smgClass::setLighteness(uint8_t l)
{
	if(l>SMG_MAX_LIGHTENESS)return 0;
	lighteness=l;	
	return 1;
}
uint8_t smgClass::setOneBitLighteness(uint8_t s,uint8_t l)
{
	uint16_t tmpValue;
	if(l>SMG_MAX_LIGHTENESS)return 0;
	if(s>=SMG_WEI_NUMBER)return 0;
	if(l==0)
	{
		tmpValue=0;
	}
	else if(l==1)
	{
		tmpValue=10;
	}
	else if(l==2)
	{
		tmpValue=40;
	}
	else if(l==3)
	{
		tmpValue=70;
	}
	switch (s)
	{
		case 0:
			htim3.Instance->CCR3=tmpValue;
			break;
		case 1:
			htim3.Instance->CCR4=tmpValue;
			break;
		case 2:
			htim3.Instance->CCR1=tmpValue;
			break;
		case 3:
			htim3.Instance->CCR2=tmpValue;
			break;
	}		
	return 1;	
}


//设置某一位的显示编码值
//d: 0-15
uint8_t smgClass::setOneBitNumber(uint8_t s,uint8_t d)
{
	uint8_t offset;
	
	if(disMode==SMG_DIS_MODE_NORMAL)
	{
		if(s>=SMG_WEI_NUMBER)return 0;
		offset=0;
	}
	else if(disMode==SMG_DIS_MODE_ROLL)
	{
		if(s>DIS_BUF_SIZE-8)return 0;
		offset=4;
	}
	if(d<16)
	{
		disBuf[offset+s]=numtab[d];
	}
	else
	{
		disBuf[offset+s]=numtab[16];   //'-'
	}
	
	return 1;
}
//设置某一位的显示数字
//d: 0-15
uint8_t smgClass::setOneBitCode(uint8_t s,uint8_t d)
{
	uint8_t offset;
	
	if(disMode==SMG_DIS_MODE_NORMAL)
	{
		if(s>=SMG_WEI_NUMBER)return 0;
		offset=0;
	}
	else if(disMode==SMG_DIS_MODE_ROLL)
	{
		if(s>DIS_BUF_SIZE-8)return 0;
		offset=4;
	}
	disBuf[offset+s]=d;
	return 1;
}
//清除显示
void smgClass::clearDis()
{
	for(uint8_t i=0;i<DIS_BUF_SIZE;i++)
	{
		disBuf[i]=0x00;
	}
}
//显示数字，最多显示4位
uint8_t smgClass::setNormalDisNumber(uint8_t *s,uint8_t length)
{
	uint8_t i=0;
	disMode=SMG_DIS_MODE_NORMAL;
	clearDis();   //原来的显示清除掉
	if(length>SMG_WEI_NUMBER)   
	{
		length=4;
	}
	for(i=0;i<length;i++)
	{
		if('0'<=s[i]&&s[i]<='9')
		{
			disBuf[i]=numtab[s[i]-'0'];	
		}
		else if('A'<=s[i]&&s[i]<='F')
		{
			disBuf[i]=numtab[s[i]-'A'+0x0A];
		}
		else if('a'<=s[i]&&s[i]<='f')
		{
			disBuf[i]=numtab[s[i]-'a'+0x0A];
		}
		else
		{
			disBuf[i]=numtab[16];
		}		
	}
	return 1;
}
//滚动显示数字，传递进来的是字符型
uint8_t smgClass::setRollDisNumber(uint8_t *s,uint8_t length)
{
	uint8_t i=0;
	disMode=SMG_DIS_MODE_ROLL;
	clearDis();   //原来的显示清除掉
	if(length>(DIS_BUF_SIZE-8))   //滚动显示时清空前后四个byte，共8个空闲
	{
		length=DIS_BUF_SIZE-8;
	}
	for(i=0;i<SMG_WEI_NUMBER;i++)
	{
		disBuf[i]=0;
	}
	for(i=0;i<length;i++)
	{
		if('0'<=s[i]&&s[i]<='9')
		{
			disBuf[SMG_WEI_NUMBER+i]=numtab[s[i]-'0'];	
		}
		else if('A'<=s[i]&&s[i]<='F')
		{
			disBuf[SMG_WEI_NUMBER+i]=numtab[s[i]-'A'+0x0A];
		}
		else if('a'<=s[i]&&s[i]<='f')
		{
			disBuf[SMG_WEI_NUMBER+i]=numtab[s[i]-'a'+0x0A];
		}
		else
		{
			disBuf[SMG_WEI_NUMBER+i]=numtab[16];
		}
		
	}
	for(i=0;i<SMG_WEI_NUMBER;i++)
	{
		disBuf[SMG_WEI_NUMBER+length+i]=0;
	}
	rollNumber=length+8;
	return 1;
}
uint8_t smgClass::setBlinkOneBit(uint8_t s)
{
	if(s>SMG_S_ALL)return 0;
	switch(s)
	{
		case SMG_S0:
			blinkTab[SMG_S0]=SMG_BLINK;
			break;
		case SMG_S1:
			blinkTab[SMG_S1]=SMG_BLINK;
			break;
		case SMG_S2:
			blinkTab[SMG_S2]=SMG_BLINK;
			break;
		case SMG_S3:
			blinkTab[SMG_S3]=SMG_BLINK;
			break;
		case SMG_S_NONE:
			blinkTab[SMG_S1]=SMG_BLINK_NONE;
			blinkTab[SMG_S2]=SMG_BLINK_NONE;
			blinkTab[SMG_S3]=SMG_BLINK_NONE;
			blinkTab[SMG_S0]=SMG_BLINK_NONE;
			break;
		case SMG_S_ALL:
			blinkTab[SMG_S1]=SMG_BLINK;
			blinkTab[SMG_S2]=SMG_BLINK;
			blinkTab[SMG_S3]=SMG_BLINK;
			blinkTab[SMG_S0]=SMG_BLINK;			
			break;
	}
	return 1;
}
void smgClass::clearBlink()
{
	blinkTab[SMG_S1]=SMG_BLINK_NONE;
	blinkTab[SMG_S2]=SMG_BLINK_NONE;
	blinkTab[SMG_S3]=SMG_BLINK_NONE;
	blinkTab[SMG_S0]=SMG_BLINK_NONE;
}

//设置要进行显示的位
uint8_t smgClass::setDisWei(uint8_t s)
{
	if(s>SMG_S_ALL)return 0;
	setOneBitLighteness(0,0);
	setOneBitLighteness(1,0);
	setOneBitLighteness(2,0);
	setOneBitLighteness(3,0);
	HAL_TIM_PWM_Stop(&htim3,SMG_S0_TIME_CH);
	HAL_TIM_PWM_Stop(&htim3,SMG_S1_TIME_CH);
	HAL_TIM_PWM_Stop(&htim3,SMG_S2_TIME_CH);
	HAL_TIM_PWM_Stop(&htim3,SMG_S3_TIME_CH);

	switch (s)
	{
		case SMG_S0:
			setOneBitLighteness(0,lighteness);
			HAL_TIM_PWM_Start(&htim3,SMG_S0_TIME_CH);				
			break;
		case SMG_S1:
			setOneBitLighteness(1,lighteness);
			HAL_TIM_PWM_Start(&htim3,SMG_S1_TIME_CH);			
			break;
		case SMG_S2:
			setOneBitLighteness(2,lighteness);
			HAL_TIM_PWM_Start(&htim3,SMG_S2_TIME_CH);				
			break;
		case SMG_S3:
			setOneBitLighteness(3,lighteness);
			HAL_TIM_PWM_Start(&htim3,SMG_S3_TIME_CH);				
			break;
		case SMG_S_NONE:
			
			break;
		case SMG_S_ALL:
			setOneBitLighteness(0,lighteness);
			setOneBitLighteness(1,lighteness);
			setOneBitLighteness(2,lighteness);
			setOneBitLighteness(3,lighteness);
			
		  HAL_TIM_PWM_Start(&htim3,SMG_S0_TIME_CH);
			HAL_TIM_PWM_Start(&htim3,SMG_S1_TIME_CH);
			HAL_TIM_PWM_Start(&htim3,SMG_S2_TIME_CH);
			HAL_TIM_PWM_Start(&htim3,SMG_S3_TIME_CH);			
			break;
	}
	return 1;
}
//该函数每1ms扫描一次
void  smgClass::scan()
{
	if(disMode==SMG_DIS_MODE_NORMAL)
	{
		normalScan();
	}
	else if(disMode==SMG_DIS_MODE_ROLL)
	{
		rollScan();
	}
}
void smgClass::normalScan()
{
	static uint8_t scanWei=SMG_S0;
	static uint16_t blinkTime=0;
	static uint8_t blinkState;    //0-no display   !0-on display
	switch (scanWei)
	{
		case SMG_S0:
			if((!blinkState)&&blinkTab[SMG_S0])    //如果该位数码管需要闪烁
			{
				setDisWei(SMG_S_NONE);
			}
			else
			{
				setDisWei(SMG_S0);
				SMG_SET_DATA(disBuf[SMG_S0]);
			}
		  	scanWei=SMG_S1;
			break;
		case SMG_S1:
			if((!blinkState)&&blinkTab[SMG_S1])    //如果该位数码管需要闪烁
			{
				setDisWei(SMG_S_NONE);
			}
			else
			{
				setDisWei(SMG_S1);
				SMG_SET_DATA(disBuf[SMG_S1]);
			}
		  	scanWei=SMG_S2;
			break;
		case SMG_S2:
			if((!blinkState)&&blinkTab[SMG_S2])    //如果该位数码管需要闪烁
			{
				setDisWei(SMG_S_NONE);
			}
			else
			{
				setDisWei(SMG_S2);
				SMG_SET_DATA(disBuf[SMG_S2]);
			}
		  	scanWei=SMG_S3;
			break;
		case SMG_S3:
			if((!blinkState)&&blinkTab[SMG_S3])    //如果该位数码管需要闪烁
			{
				setDisWei(SMG_S_NONE);
			}
			else
			{
				setDisWei(SMG_S3);
				SMG_SET_DATA(disBuf[SMG_S3]);
			}
		  	scanWei=SMG_S0;
			break;
	}
	blinkTime++;
	if(blinkTime>400)
	{
		blinkTime=0;
		blinkState=!blinkState;
	}
}
void smgClass::rollScan()
{
	static uint8_t scanWei=SMG_S0;
	static uint16_t rollTime=0;
	switch (scanWei)
	{
		case SMG_S0:
			setDisWei(SMG_S0);
			SMG_SET_DATA((uint8_t)*(disBuf+rollOffset));
			scanWei=SMG_S1;
			break;
		case SMG_S1:
			setDisWei(SMG_S1);
			SMG_SET_DATA((uint8_t)*(disBuf+rollOffset+1));
			scanWei=SMG_S2;
			break;
		case SMG_S2:
			setDisWei(SMG_S2);
			SMG_SET_DATA((uint8_t)*(disBuf+rollOffset+2));
			scanWei=SMG_S3;
			break;
		case SMG_S3:
			setDisWei(SMG_S3);
			SMG_SET_DATA((uint8_t)*(disBuf+rollOffset+3));
			scanWei=SMG_S0;
			break;
	}
	rollTime++;
	if(rollTime>=400)
	{
		rollTime=0;
		rollOffset++;
		if((rollOffset+4)>=rollNumber)
		{
			rollOffset=0;
		}
	}
}

